#include "string.h"
namespace wanghao
{
    const size_t string::npos = -1;
    //普通对象迭代器
     using iterator = char*;
     //const对象迭代器
     using const_iterator = const char*;
    //无参构造
    // string::string()
    //     :_str(new char[1]{'\0'})
    //     ,_capacity(0)
    //     ,_size(0)
    // {}
    //带参构造
    string::string(const char* str)
        :_size(strlen(str))
    {
        //申请空间
        _str = new char[_size + 1];
        _capacity = _size;
        //挪动数据
        for(int i = 0;i < _size;i++)
        {
            *(_str + i) = *(str + i);
        }
    }
    //析构函数
    string::~string()
    {
        //清理资源
        delete[] _str;
        _str = nullptr;
        _size = _capacity = 0;
    }
    //返回底层的指针
    const char* string::c_str() const
    {
        return _str;
    }
    //返回size
    size_t string::size() const
    {
        return _size;
    }
    //返回capacity
    size_t string::capacity() const
    {
        return _capacity;
    }
    //下标+[]遍历 const
    const char& string::operator[](size_t i) const
    {
        assert(i < _size);
        return *(_str + i);
    }
    //下标+[]遍历
    char& string::operator[](size_t i)
    {
        assert(i < _size);
        return *(_str + i);
    }
    //begin返回开始的位置 - 左闭
    iterator string::begin()
    {
        return _str;
    }
    //end返回结束位置的下一个位置 - 右开
    iterator string::end()
    {
        return _str + _size;
    }
    //const迭代器begin
    const_iterator string::begin() const
    {
        return _str;
    }
    //const迭代器end
    const_iterator string::end() const
    {
        return _str + _size;
    }
    //扩容
    void string::reserve(size_t n)
    {
        //传入的值大于当前空间容量的话就存在扩容
        //开空间永远要多开一个
        if(n > _capacity)
        {
            char* newStr = new char[n + 1];
            //拷贝数据
            for(int i = 0;i < _size;i++)
            {
                *(newStr + i) = *(_str + i);
            }
            //释放旧空间
            delete[] _str;
            _str = newStr;
            newStr = nullptr;
            _capacity = n;
        }
    }
    //尾插一个字符
    void string::push_back(char c)
    {
        //首先判断空间是否足够
        if(_size == _capacity)
        {
            reserve(_capacity == 0 ? 4 : 2 * _capacity);
        }
        *(_str + _size) = c;
        _size++;
    }
    //尾插一个字符串
    void string::append(const char* str)
    {
        size_t len = strlen(str);
        if(_size + len > _capacity)
        {
            size_t newCapacity = 2 * _capacity;
            if(newCapacity < _size + len)
                newCapacity = _size + len;
            reserve(newCapacity);
        }
        //尾插
        for(int i = 0;i < len;i++)
        {
            *(_str + _size++) = *(str + i);
        }
    }
    //+=一个字符
    string& string::operator+=(char c)
    {
        push_back(c);
        return *this;
    }
    //+=一个字符串
    string& string::operator+=(const char* str)
    {
        append(str);
        return *this;
    }
    //pos位置插入一个字符
    void string::insert(size_t pos,char c)
    {
        assert(pos <= _size);
        //首先判断空间是否足够
        if(_size == _capacity)
        {
            reserve(_capacity == 0 ? 4 : 2 * _capacity);
        }
        //挪动数据
        for(int i = _size + 1;i > pos;i--)
        {
            *(_str + i) = *(_str + i - 1);
        }
        *(_str + pos) = c;
        _size++;
    }
    //pos位置插入一个字符串
    void string::insert(size_t pos,const char* str)
    {
        assert(pos <= _size);
        size_t len = strlen(str);
        //首先判断空间是否足够
        if(_size + len > _capacity)
        {
            size_t newCapacity = 2 * _capacity;
            if(newCapacity < _size + len)
                newCapacity = _size + len;
            reserve(newCapacity);
        }
        //移动数据
        for(int i = _size + len; i >= pos + len;i--)
        {
            *(_str + i) = *(_str + i - len);
        }
        //插入数据
        size_t count = 0;
        for(int i = pos;i < pos + len;i++)
        {
            *(_str + i) = *(str + count++); 
        }
        _size += len;
    }
    //从pos位置开始删除len个字符
    void string::erase(size_t pos,size_t len)
    {
        assert(pos < _size);
        if(len >= _size - pos)
        {
            *(_str + pos) = '\0';
            _size = pos;
        }
        else
        {
            //挪动数据
            for(int i = pos + len;i <= _size;i++)
            {
                *(_str + i - len) = *(_str + i);
            }
            _size -= len;
        }
    }
    //从pos位置开始查找字符
    size_t string::find(char ch,size_t pos)
    {
        assert(pos < _size);
        for(int i = pos;i < _size;i++)
        {
            if(*(_str + i) == ch)
                return i;
        }
        return npos;
    }
    //从pos位置开始查找字符串
    size_t string::find(const char* str,size_t pos)
    {
        assert(pos < _size);
        const char* ptr = strstr(_str + pos,str);
        if(ptr == nullptr)
        {
            return npos;
        }
        else
        {
            return ptr - _str;
        }
    }
    //取子串
    string string::substr(size_t pos,size_t len)
    {
        assert(pos < _size);
        if(len > (_size - pos))
        {
            len = _size - pos;
        }
        wanghao:;string sub;
        sub.reserve(len);
        for(int i = 0;i < len;i++)
        {
            sub += *(_str + pos + i);
        }
        return sub;
    }
    //拷贝构造
    string::string(const string& s)
    {
        _capacity = s._capacity;
        _size = s._size;
        _str = new char[_capacity + 1];
        for(int i = 0;i < _size;i++)
        {
            *(_str + i) = *(s._str + i);
        }
    }
    //赋值构造
    string& string::operator=(const string& s)
    {
        //写法1----------------------------:
        if(this != &s)
        {
            _size = s._size;
            _capacity = s._capacity;
            delete[] _str;
            _str = new char[_size + 1];
            //拷贝数据
            for(int i = 0;i < _size;i++)
            {
                *(_str + i) = *(s._str + i);
            }
        }
        //写法2----------------------------:
        //wanghao::string tmp(s);
        //swap(tmp);
    }
    //交换函数
    void string::swap(string& s)
    {
        std::swap(_size,s._size);
        std::swap(_capacity,s._capacity);
        std::swap(_str,s._str);
    }
    //清空
    void string::clear()
    {
        delete[] _str;
        _str = new char[1]{'\0'};
        _size = 0;
        _capacity = 0;
    }
    //类交换函数
    void swap(string& s1,string& s2)
    {
        s1.swap(s2);
    }
    //字符串比较函数
    int StrCmp(const char* s1,const char* s2)
    {
        return strcmp(s1,s2);
    }
    //==
    bool operator==(const string& lhs,const string& rhs)
    {
        return !StrCmp(lhs.c_str(),rhs.c_str());
    }
    //!=
    bool operator!=(const string& lhs,const string& rhs)
    {
        return !(lhs == rhs);
    }
    //>
    bool operator>(const string& lhs,const string& rhs)
    {
        return StrCmp(lhs.c_str(),rhs.c_str()) > 0;
    }
    //<
    bool operator<(const string& lhs,const string& rhs)
    {
        return StrCmp(lhs.c_str(),rhs.c_str()) < 0;
    }
    //>=
    bool operator>=(const string& lhs,const string& rhs)
    {
        return !(lhs < rhs);
    }
    //<=
    bool operator<=(const string& lhs,const string& rhs)
    {
        return !(lhs > rhs);
    }
    //流插入
    ostream& operator<<(ostream& out,const string& str)
    {
        //这里可以输出c_str(),但这个函数在极端的情况下会出问题
        for(int i = 0;i < str.size();i++)
        {
            out << str[i];
        }
        return out;
    }
    //流提取
    istream& operator>>(istream& in,string& str)
    {
        str.clear();
        int i = 0;
        //栈上开空间
        char buff[256];
        char ch = '\0';
        ch = in.get();
        while(ch != ' ' && ch != '\n')
        {
            buff[i++] = ch;
            if(i == 255)
            {
                buff[i] = '\0';
                str += buff;
                i = 0;
            }
            ch = in.get();
        }
        if(i > 0)
        {
            buff[i] = '\0';
            str += buff;
        }
        return in;
    }
    //getline
    istream& getline(istream& in,string& str,char delim)
    {
        str.clear();
        int i = 0;
        //栈上开空间
        char buff[256];
        char ch = '\0';
        ch = in.get();
        //自己定义结束标志
        while(ch != delim)
        {
            buff[i++] = ch;
            if(i == 255)
            {
                buff[i] = '\0';
                str += buff;
                i = 0;
            }
            ch = in.get();
        }
        if(i > 0)
        {
            buff[i] = '\0';
            str += buff;
        }
        return in;
    }
}